package com.fzj.charging.cost.service.impl;


import com.fzj.charging.common.pojo.param.ChargingProcessParam;
import com.fzj.charging.common.pojo.vo.ChargingProcessVO;
import com.fzj.charging.cost.dao.repository.CostESRepository;
import com.fzj.charging.cost.dao.repository.CostRedisRepository;
import com.fzj.charging.cost.dao.repository.CostRepository;
import com.fzj.charging.cost.pojo.entity.ChargingCostRule;
import com.fzj.charging.cost.pojo.entity.ChargingDataES;
import com.fzj.charging.cost.service.CostService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class CostServiceImpl implements CostService {
    @Autowired
    private CostRepository costRepository;
    @Autowired
    private CostESRepository costESRepository;
    @Autowired
    private CostRedisRepository costRedisRepository;
    //HashMap<String, ChargingData> chargingMap = new HashMap<>();

    @Override
    public ChargingProcessVO calculateCost(ChargingProcessParam chargingProcessParam) {
        log.debug("计算费用业务，参数：{}",chargingProcessParam);
        Integer timeNow = getTimeNowHour();
        log.debug("计算费用业务，获取当前小时，结果：{}",timeNow);
        ChargingCostRule costRuleByGunTypeAndTime = getCostRuleByGunTypeAndTime(chargingProcessParam.getStationId(), chargingProcessParam.getGunType(), timeNow);
        log.debug("计算费用业务，获取计价规则，参数：{},计价规则：{}",chargingProcessParam,costRuleByGunTypeAndTime);
        ChargingProcessVO chargingProcessVO = null;
        if(costRuleByGunTypeAndTime!=null){
            String orderNo = chargingProcessParam.getOrderNo();//订单号
            String name = costRuleByGunTypeAndTime.getName();//计费名称
            BigDecimal powerFee = costRuleByGunTypeAndTime.getPowerFee();//电费单价
            Float electricity = chargingProcessParam.getElectricity();//本次同步充电度数
            Optional<ChargingDataES> optional = costESRepository.findById(orderNo);
            if(optional.isPresent()){
                //第n次
                ChargingDataES chargingDataES = optional.get();
                Float electricityAdd = electricity-chargingDataES.getTotalElectricity();//较上次增加的度数
                BigDecimal onceChargingFee = getOnceChargingFee(electricityAdd, powerFee);//本次增加的电费
                chargingDataES.setCount(chargingDataES.getCount()+1);
                chargingDataES.setTotalChargingFee(chargingDataES.getTotalChargingFee().add(onceChargingFee));
                chargingDataES.setTotalElectricity(electricity);
                log.debug("第{}次同步，计费名称：{}，当前小时数：{}，" +
                                "电费单价：{}，同步的充电度数：{}，" +
                                "增加的电费：{}，充电总费用：{}",
                        chargingDataES.getCount(),name,timeNow,
                        powerFee,electricity,
                        onceChargingFee,chargingDataES.getTotalChargingFee());
                log.debug("保存到ES的充电数据：{}",chargingDataES);
                costESRepository.save(chargingDataES);
                chargingProcessVO = buildChargingProcessVO(chargingDataES,chargingProcessParam.getGunId());

            }else{
                //第1次
                BigDecimal onceChargingFee = getOnceChargingFee(electricity,powerFee);
                ChargingDataES chargingDataES = new ChargingDataES();
                chargingDataES.setId(orderNo);
                chargingDataES.setOrderNo(orderNo);
                chargingDataES.setCount(1);
                chargingDataES.setTotalElectricity(electricity);
                chargingDataES.setTotalChargingFee(onceChargingFee);
                chargingDataES.setStartTime(new Date().getTime()/1000);
                log.debug("第{}次同步，计费名称：{}，当前小时数：{}，" +
                                "电费单价：{}，同步的充电度数：{}，" +
                                "增加的电费：{}，充电总费用：{}",
                        chargingDataES.getCount(),name,timeNow,
                        powerFee,electricity,
                        onceChargingFee,chargingDataES.getTotalChargingFee());
                log.debug("保存到ES的充电数据：{}",chargingDataES);
                costESRepository.save(chargingDataES);
                chargingProcessVO = buildChargingProcessVO(chargingDataES,chargingProcessParam.getGunId());
            }

            /*if(chargingMap.get(orderNo)==null){
                ChargingData chargingData = new ChargingData();
                chargingData.setOrderNo(orderNo);
                chargingData.setCount(1);
                chargingData.setTotalElectricity(electricity);
                BigDecimal onceChargingFee = getOnceChargingFee(electricity, powerFee);//本次充电费用
                log.debug("第{}次同步，计费名称：{}，当前小时数：{}，" +
                                "电费单价：{}，单次充电度数：{}，" +
                                "充电费用：{}，充电总费用：{}",
                        chargingData.getCount(),name,timeNow,
                        powerFee,electricity,
                        onceChargingFee,onceChargingFee);
                chargingData.setTotalChargingFee(onceChargingFee);
                chargingMap.put(orderNo,chargingData);
            }else{
                ChargingData chargingData = chargingMap.get(orderNo);
                Float electricityAdd = chargingProcessParam.getElectricity()-chargingData.getTotalElectricity();//本次同步充电度数较上次增加的度数
                BigDecimal onceChargingFee = getOnceChargingFee(electricityAdd, powerFee);//本次充电费用
                chargingData.setCount(chargingData.getCount()+1);
                chargingData.setTotalElectricity(electricity);
                chargingData.setTotalChargingFee(chargingData.getTotalChargingFee().add(onceChargingFee));
                log.debug("第{}次同步，计费名称：{}，当前小时数：{}，" +
                                "电费单价：{}，单次充电度数：{}，" +
                                "充电费用：{}，充电总费用：{}",
                        chargingData.getCount(),name,timeNow,
                        powerFee,electricity,
                        onceChargingFee,chargingData.getTotalChargingFee());
            }*/
        }else{
            log.debug("计费规则为空，系统故障，进行告警，业务无法进行");
        }
        log.debug("计算费用业务，参数：{},结果：{}",chargingProcessParam,chargingProcessVO);
        return chargingProcessVO;
    }
    public List<ChargingCostRule> getCostRuleList(Integer stationId){
        List<ChargingCostRule> chargingCostRuleList = costRedisRepository.selectCostRuleList(stationId);
        if(chargingCostRuleList!=null&&!chargingCostRuleList.isEmpty()){
            log.debug("根据场站id:{},从redis中查询到计价规则列表:{}",stationId,chargingCostRuleList);
            return chargingCostRuleList;
        }else{
            List<ChargingCostRule> dbCostRuleByStationId = costRepository.getCostRuleByStationId(stationId);
            if(dbCostRuleByStationId!=null&&!dbCostRuleByStationId.isEmpty()){
                log.debug("根据场站id:{},从数据库中查询到计价规则列表:{}",stationId,dbCostRuleByStationId);
                costRedisRepository.saveCostRuleList(stationId,dbCostRuleByStationId);//存入到redis
                return dbCostRuleByStationId;
            }else {
                log.debug("计费规则为空，系统故障，进行告警，业务无法进行");
                return null;
            }
        }
    }

    public ChargingCostRule getCostRuleByGunTypeAndTime(Integer stationId,Integer gunType,Integer timeNow){
        log.debug("获取计价规则列表，场站id：{}",stationId);
        List<ChargingCostRule> costRuleList = getCostRuleList(stationId);
        log.debug("获取计价规则列表，场站id：{}，计价规则列表：{}",stationId,costRuleList);
        if(!CollectionUtils.isEmpty(costRuleList)){
            for(ChargingCostRule chargingCostRule : costRuleList){
                if(gunType.equals(chargingCostRule.getGunType())){
                    if(timeNow >=chargingCostRule.getStartTime()&&timeNow < chargingCostRule.getEndTime()){
                        return chargingCostRule;
                    }
                }
            }
        }
        return null;
    }


    /**
     * 获取当前时间小时数
     * @return
     */
    public Integer getTimeNowHour(){
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.getHour();
    }

    /**
     * 计算本次充电价格 本次同步充电度数 * 电费单价
     * @param electricity
     * @param powerFee
     * @return
     */
    public BigDecimal getOnceChargingFee(Float electricity,BigDecimal powerFee){
        //  参数1：代表小数点后位数
        //	参数2：	BigDecimal.ROUND_HALF_UP 四舍五入
        //			BigDecimal.ROUND_DOWN 直接删除多余小数位

        return powerFee.multiply(new BigDecimal(electricity)).setScale(4,BigDecimal.ROUND_HALF_UP);

    }

    /**
     * 构建充电返回结果
     * @return
     */
    public ChargingProcessVO buildChargingProcessVO(ChargingDataES chargingDataES,Integer gunId){
        ChargingProcessVO chargingProcessVO = new ChargingProcessVO();
        chargingProcessVO.setOrderNo(chargingDataES.getOrderNo());
        chargingProcessVO.setElectricity(chargingDataES.getTotalElectricity());
        chargingProcessVO.setTotalChargingFee(chargingDataES.getTotalChargingFee());
        chargingProcessVO.setGunId(gunId);
        if(chargingDataES.getCount()==1){
            chargingProcessVO.setTimeTotal(0L);
        }else {
            chargingProcessVO.setTimeTotal(new Date().getTime()/1000-chargingDataES.getStartTime());
        }
        return chargingProcessVO;
    }
}
